#!/usr/bin/python3
# -*- coding:utf-8 -*-
import re
import traceback

from selenium.webdriver import ActionChains

from qturboframe.lib.utils.CustomError.custom_error import CustomError
from qturboframe.lib.utils.by import By
from qturboframe.lib.webdriver.exceptions import SeleniumError
from qturboframe.lib.report.log import logger
from qturboframe.public_ui.h_ui.select import Select as HuiSelect
import time

from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC


class Select(HuiSelect):
    '''
    对下拉框进行封装
    对操作员中心有的菜单右侧的其他checkbox进行封装
    '''

    def set_value_for_single(self, value, timeout=3):
        """
        hui单选下拉框选择

        :Args:
         - value: 选择项的文本
         - timeout: 超时时间，默认是20s

        :Example:
         - 例1: select.set_value_for_single('苹果')
         - 例2: select.set_value_for_single('苹果',timeout=5)
        """
        select_section = self.element.find_element_by_attribute(
            'css selector', 'div.h-select-selection')
        try:
            # 当元素被覆盖，则无法点击
            select_section.click()
        except Exception:
            self._driver.execute_script("arguments[0].click();", select_section)
        # 显示等待下拉列表加载出来后，滚动下拉框选择
        waitFlag = WebDriverWait(self.element.parent, timeout, 0.5).until(
            EC.presence_of_element_located(
                (By.XPATH, './/div[@class="h-select-dropdown"]/div/ul/li')))
        select_result = True
        error_sys = None
        try:
            if waitFlag:
                input_element = self._element.exist(
                    'css selector', 'div.h-select-selection>input', timeout=0.1)
                if input_element:
                    input_element.send_keys(value)
                div_list = self.element.find_element_by_attribute(By.XPATH, './/div[@class="h-select-dropdown-content"]')
                # 将页面滚动到 顶部
                action = ActionChains(driver=self.element.parent)
                action.move_to_element(div_list)
                action.perform()
                fundFlag = False
                index = 0
                while index < 10:
                    liEleXpath = f'.//ul/li'
                    selectLists = div_list.find_elements_by_attribute(By.XPATH, liEleXpath, timeout=1)
                    if len(selectLists) > 0:
                        for ele in selectLists:
                            cur_txt = ele.text
                            # logger.debug(f"当前下拉框的选项：{cur_txt}")
                            if ele.is_displayed() and ele.is_enabled() and re.search(value, cur_txt, re.IGNORECASE):
                                ele.click()         # 模糊匹配会匹配到多的，所以需要去点击当前下拉框可见的
                                fundFlag = True
                                break
                        if fundFlag:
                            break
                    else:
                        action.send_keys(Keys.PAGE_DOWN * 5).perform()
                        index += 1
                        logger.warning(f"No.{index}：当前页没有找到待勾选的元素：{value}，向下滚动")
                if not fundFlag:
                    logger.error(f"下翻查找 {index} 次，仍然没有找到待勾选的元素：{value}")
                    raise SeleniumError(f"下翻查找 {index} 次，仍然没有找到待勾选的元素：{value}")
            else:
                logger.error("下拉元素尚未加载！")
        except Exception as e:
            logger.error(f"下拉框选择元素失败，错误信息：{e}")
            logger.error(traceback.format_exc())
            select_result = False
            error_sys = e
        if not select_result:
            raise SeleniumError(f"下拉框选择元素失败，错误信息：{error_sys}")

    def set_value_for_multiple(self, value: list = None, timeout=3):
        """
        hui的多选下拉框选择

        :Args:
         - value: 选择项的文本集合
         - timeout: 超时时间，默认是20s

        :Example:
         - 例1: select.set_value_for_multiple(['香蕉','苹果','葡萄'])
         - 例2: select.set_value_for_multiple(['香蕉','苹果','葡萄'], 5)
        """
        # 先全部清空
        self.clear_for_multiple()
        # 弹出下拉框
        selectElement = self._element.find_element_by_attribute(
            'css selector', 'div.h-select-selection', timeout=self.timeout)
        selectElement.secure_click()
        select_div = self._element.exist(
            'css selector', 'div.h-select-dropdown', timeout=0.1)
        if not select_div:
            select_div = self._driver.find_element_by_attribute(
                'xpath', '//div[contains(@class, "h-select-dropdown") and contains(@class, "h-select-multiple") and '
                         'not(contains(@style, "display: none;"))]',
                timeout=self.timeout)
        inputElement = select_div.exist(
            'css selector', 'div.h-select-dropdown-content>span>input',
            timeout=0.1)
        if value[0] in ["全选", "全不选"]:
            buttonName = value[0]
            allButton = select_div.find_element_by_attribute(
                'css selector', 'div.h-select-checkall>button>span', f'text:{buttonName}', timeout=3)
            allButton.click()
        else:
            groupElements = select_div.find_elements_by_attribute(
                'css selector', 'div.h-select-dropdown-content>ul.h-select-dropdown-list>li.h-select-group-wrap',
                timeout=2)
            if groupElements:
                for unit in value:
                    first, second = unit.split('-')
                    target = f'//ul[@class="h-select-dropdown-list"]/li/div[text()="{first}"]' \
                             f'/following-sibling::ul/li/li[contains(text(), "{second}")]'
                    elements = select_div.find_elements_by_attribute('xpath', target, timeout=2)
                    if elements:
                        for ele in elements:
                            if ele.is_displayed():
                                ele.secure_click()
                    else:
                        logger.warning(f"没有找到{unit}")
            else:
                for text in value:
                    if inputElement:
                        inputElement.send_keys(text)
                        inputElement.send_keys(Keys.ENTER)   # 此处直接回车可以选择
                    else:
                        # 显性等待，直到用户名控件加载出来才进行下一步
                        waitFlag = WebDriverWait(self._driver, timeout, 0.5).until(
                            EC.presence_of_element_located(
                                (By.XPATH, '//div[@class="h-select-dropdown"]//ul[@class="h-select-dropdown-list"]/li')))
                        if waitFlag:
                            select_list = select_div.find_elements_by_attribute(
                                By.XPATH,
                                f'//div[@class="h-select-dropdown"]//ul[@class="h-select-dropdown-list"]/'
                                f'li[contains(text(), "{text}")]',
                                timeout=self.timeout)
                            if len(select_list) > 0:
                                select_list[0].secure_click()
                                logger.info(f"勾选元素：{value}")
                            else:
                                logger.error(f"没有找到待勾选的元素：{value}")
                                raise SeleniumError(f"没有找到待勾选的元素：{value}")
                        else:
                            logger.error("下拉元素尚未加载！")
        selectElement.secure_click()

    def set_value_for_loading_multiple(self, value, timeout=20):
        """
        下拉继续加载的多选下拉框选择（label为角色信息）

        :Args:
         - value: 选择项的文本集合
        """
        select_ul_class = r'h-select-dropdown-list'
        # 先全部清空
        self.clear_for_multiple()
        # 弹出下拉框
        self._element.find_element_by_attribute(
            'css selector', 'div.h-select-selection', timeout=self.timeout).secure_click()
        select_div = self._element.find_element_by_attribute(
            'css selector', 'div.h-select-dropdown', timeout=self.timeout)
        timeout1 = 0
        while timeout1 < timeout * 10:
            select_ul = select_div.exist('css selector', 'ul.' + select_ul_class, timeout=0.1)
            if select_ul:
                if select_ul.is_displayed():
                    break
            timeout1 += 1
            time.sleep(0.1)
        else:
            raise SeleniumError('下拉框中没有数据！')
        for text in value:
            select_li = select_ul.exist('css selector', 'li', 'text:'.format(text), timeout=0.1)
            latest_uls = None
            old_uls = 1
            uls = select_ul.find_elements_by_attribute('tag name', 'li', timeout=self.timeout)
            while not select_li:
                if latest_uls == old_uls:
                    raise SeleniumError('无法找到对应的选项')
                old_uls = uls
                uls = select_ul.find_elements_by_attribute('tag name', 'li', timeout=self.timeout)
                uls[-1].find_element_by_attribute('css selector', 'span.h-checkbox', timeout=self.timeout).focus()
                select_li = select_ul.exist('css selector', 'li', 'text:' + text, timeout=0.1)
                latest_uls = uls
            select_li.find_element_by_attribute('css selector', 'span.h-checkbox', timeout=self.timeout).secure_click()

    def set_value_for_loading_single(self, value, timeout=20):
        """
        下拉继续加载的单选下拉框选择(消息系统，label为消息收发件人)

        :Args:
         - value: 选择项的文本集合
        """
        select_ul_class = r'h-select-dropdown-list'
        # 弹出下拉框
        self._element.find_element_by_attribute(
            'css selector', 'div.h-select-selection', timeout=self.timeout).secure_click()
        select_div = self._element.find_element_by_attribute(
            'css selector', 'div.h-select-dropdown', timeout=self.timeout)
        timeout1 = 0
        while timeout1 < timeout * 10:
            select_ul = select_div.exist('css selector', 'ul.' + select_ul_class, timeout=0.1)
            if select_ul:
                if select_ul.is_displayed():
                    break
            timeout1 += 1
            time.sleep(0.1)
        else:
            raise SeleniumError('下拉框中没有数据！')
        select_li = select_ul.exist('css selector', 'li', 'text:'.format(value), timeout=0.1)
        latest_uls = None
        old_uls = 1
        uls = select_ul.find_elements_by_attribute('tag name', 'li', timeout=self.timeout)
        while not select_li:
            if latest_uls == old_uls:
                raise SeleniumError('无法找到对应的选项')
            old_uls = uls
            uls = select_ul.find_elements_by_attribute('tag name', 'li', timeout=self.timeout)
            uls[-1].focus()
            select_li = select_ul.exist('css selector', 'li', 'text:' + value, timeout=self.timeout)
            latest_uls = uls
        select_li.secure_click()

    def set_value_for_pop_single_type(self, value, timeout=20):
        """
        处理下拉框数据以弹框形式展示的单选下拉框（例：label为证书类型的，等）

        :Args:
         - value: 选择项的文本
         - timeout: 超时时间，默认是20s

        :Example:
         - 例1: select.set_value_for_certificate_type('苹果')
         - 例2: select.set_value_for_certificate_type('苹果',timeout=5)
        """
        select_ul_class = r'h-select-dropdown-list'
        self._element.find_element_by_attribute(
            'css selector', 'div.h-select-selection', timeout=self.timeout).secure_click()     
        select_div = self._driver.find_element_by_attribute(
            'css selector', 'div.h-select-dropdown.h-select-dropdown-transfer.v-transfer-dom', timeout=self.timeout)
        timeout1 = 0
        while timeout1 < timeout * 10:
            select_ul = select_div.exist('css selector', 'ul.' + select_ul_class, timeout=0.1)
            if select_ul.is_displayed():
                break
            timeout1 += 1
            time.sleep(0.1)
        else:
            raise SeleniumError('下拉框中没有数据！')
        select_ul.find_element_by_attribute(
            'tag name', 'li', 'text:' + value, timeout=self.timeout).secure_click()

    def is_default_for_single(self, value):
        """
        检查操作员中心单选下拉框默认值
        重写说明：操作员中心下拉框默认值有在h-select-input弹框中的，需要兼容到

        :Args:
         - value: 待检查的选项值

        :Returns:
            匹配返回True，否则返回False

        :Example:
         - 例: select.is_default_for_single('香蕉')
        """
        span_value = self._element.find_element_by_attribute(
            'css selector', 'div.h-select-selection>span.h-select-selected-value', timeout=0.1)
        text = span_value.text
        if text:
            if value == text:
                return True
            else:
                logger.error('默认值不匹配！')
                return False
        span_default = self._element.exist(
            'css selector', 'div.h-select-selection>span.h-select-placeholder', timeout=0.1)
        if span_default and span_default.is_displayed():
            text = span_default.text
            if value == text:
                return True
            else:
                logger.error('默认值不匹配！')
                return False
        input_default = self._element.exist('css selector', 'input.h-select-input', timeout=self.timeout)
        if input_default:
            if input_default.text:
                text = input_default.text
            elif input_default.get_attribute('value'):
                text = input_default.get_attribute('value')
            elif input_default.get_attribute('placeholder'):
                text = input_default.get_attribute('placeholder')
            elif input_default.get_attribute('title'):
                text = input_default.get_attribute('title')
            else:
                text = ''
            if value == text:
                return True
            else:
                logger.error('默认值不匹配！')
                return False
        else:
            logger.error('没有默认值！')
            return False

    def is_default_for_multiple(self, value):
        """
        检查操作员中心多选下拉框默认值
        重写说明：操作员中心下拉框默认值有在h-select-input弹框中的，需要兼容到

        :Args:
         - value: 待检查的选项值

        :Returns:
            匹配返回True，否则返回False

        :Example:
         - 例: select.is_default_for_multiple('香蕉,苹果,葡萄')
        """
        span_value_list = self._element.find_elements_by_attribute(
            'css selector', 'div.h-select-selection>div.h-tag>span.h-tag-text', timeout=0.1)
        if span_value_list:
            for span_value in span_value_list:
                text = span_value.text
                for va in value:
                    if va == text:
                        break
                else:
                    logger.error('默认值不匹配！')
                    return False
            else:
                return True
        span_default = self._element.exist(
            'css selector', 'div.h-select-selection>span.h-select-placeholder', timeout=0.1)
        if span_default and span_default.is_displayed():
            text = span_default.text
            if value[0] == text:
                return True
            else:
                logger.error('默认值不匹配！')
                return False
        input_default = self._element.exist('css selector', 'input.h-select-input', timeout=self.timeout)
        if input_default:
            if input_default.text:
                text = input_default.text
            elif input_default.get_attribute('value'):
                text = input_default.get_attribute('value')
            elif input_default.get_attribute('placeholder'):
                text = input_default.get_attribute('placeholder')
            elif input_default.get_attribute('title'):
                text = input_default.get_attribute('title')
            else:
                text = ''
            if value[0] == text:
                return True
            else:
                logger.error('默认值不匹配！')
                return False
        else:
            logger.error('没有默认值！')
            return False